package com.lc.aop;

import com.lc.config.annos.Exclude;
import com.lc.config.annos.Transactional;
import com.lc.datasource.DataSourceContext;

import javax.sql.DataSource;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.SQLException;

/**
 * @author liuc
 * @date 2021/4/18
 * @description
 **/
@Exclude
public class TransactionMethod implements AroundMethod{

    private Object o;
    private DataSourceContext dataSourceContext;

    public TransactionMethod(DataSourceContext dataSourceContext, Object o) {
        //System.out.println(dataSourceContext);
        this.dataSourceContext = dataSourceContext;
        this.o = o;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object... args) throws Exception {
        //判断是否需要开启事务
        if(needTransaction(method)){
            return invokeTransactional(proxy,method,args);
        }else{
            return invokeNormal(proxy,method,args);
        }
    }

    private Object invokeNormal(Object proxy, Method method, Object... args) throws InvocationTargetException, IllegalAccessException {
        System.out.println("invoke normal");
        return method.invoke(o,args);
    }

    private Object invokeTransactional(Object proxy, Method method, Object... args) throws SQLException, InvocationTargetException, IllegalAccessException {
        Connection connection = dataSourceContext.getConnection();
        connection.setAutoCommit(false);
        Object result = null;
        try {
            result = method.invoke(o,args);
            connection.commit();
            //todo 2.提交事务
        } catch (Exception e){
            //todo 2.回滚事务
            connection.rollback();
            throw e;
        }
        return result;
    }

    private boolean needTransaction(Method method){
        //todo jdk 代理后注解没了
        //cglib 代理后属性没了
        for (Annotation annotation : method.getAnnotations()) {
            if(annotation instanceof Transactional){
                return true;
            }
        }
        return false;
    }
}
